package com.deng.eventflow.core.functions;

import com.deng.eventflow.core.Context;
import com.deng.eventflow.core.EventTracker;
import com.deng.eventflow.core.FutureDone;

import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

public abstract class Function implements DuplicableFunction {
    public static final int s_maxInputArity = 10;

    public void evaluate( Object[] inputs, Object[] outputs,  Context context) {
        evaluate(inputs, outputs, context, null);
    }

    public abstract void evaluate (Object[] inputs, Object[] outputs, Context context, EventTracker tracker);

    public void evaluate(Object[] inputs, Object[] outputs) {
        evaluate(inputs, outputs, null);
    }

    public boolean evaluatePartial(Object[] inputs, Object[] outputs, Context context) {
        // Defer the call to evaluate if any input is null
        for (Object input : inputs) {
            if (input == null) {
                return false;
            }
        }
        evaluate(inputs, outputs, context);
        return true;
    }

    public boolean evaluateLazy(Object[] inputs, Object[] outputs) {
        return evaluatePartial(inputs, outputs, null);
    }

    public abstract int getInputArity();

    public abstract int getOutputArity();

    public void reset(){}

    public abstract void getInputTypesFor(Set<Class<?>> classes, int index);

    public abstract Class<?> getOutputTypeFor(int index);

    public Future<Object[]> evaluateFast(Object[] inputs, Object[] outputs, Context context, ExecutorService service) {
        evaluate(inputs, outputs, context);
        return new FutureDone<Object[]>(outputs);
    }

    @Override
    /*@ pure non_null @*/ public final Function duplicate() {
        return duplicate(false);
    }

    @Override
    /*@ pure non_null @*/ public abstract Function duplicate(boolean with_state);

    protected Object printState() {
        return null;
    }

    protected Function readState(Object o) {
        throw new UnsupportedOperationException("This function does not support deserialization");
    }

}
